package com.gy.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gy.controller.common.UserHolder;
import com.gy.entity.LoginUser;
import com.gy.entity.User;
import com.gy.mapper.UserMapper;
import com.gy.result.Result;
import com.gy.service.UserService;
import com.gy.user.LogoutRequest;
import com.gy.user.UserLoginRequest;
import com.gy.user.UserRegisterRequest;
import com.gy.vo.UpdatePasswordRequest;
import com.gy.vo.UserLoginVO;
import com.gy.vo.UserPersonalVO;
import com.gy.vo.UserResultCountVO;
import com.gy.vo.form.AddMemberVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.gy.constant.RedisConstants.LOGIN_USER_KEY;
import static com.gy.constant.RedisConstants.LOGIN_USER_TTL;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private PasswordEncoder passwordEncoder;
    /**
     * 用户登录
     */
    public static final String SALT = "ndnu";
    @Override
    public Result<UserLoginVO> userLogin(UserLoginRequest userLoginRequest, HttpServletRequest request) {
        // 1. 校验验证码
        String uuid = userLoginRequest.getUuid();
        String userCaptcha = userLoginRequest.getCaptcha();

        if (StringUtils.isBlank(uuid)) {
            return Result.error("验证码标识不能为空");
        }
        if (StringUtils.isBlank(userCaptcha)) {
            return Result.error("验证码不能为空");
        }

        // 从 Redis 中获取验证码
        String redisKey = "CAPTCHA:" + uuid;
        String correctCaptcha = stringRedisTemplate.opsForValue().get(redisKey);

        if (StringUtils.isBlank(correctCaptcha)) {
            return Result.error("验证码已过期，请刷新验证码");
        }

        // 校验验证码
        if (!userCaptcha.equalsIgnoreCase(correctCaptcha)) {
            return Result.error("验证码错误");
        }

        // 验证码校验通过后，删除 Redis 中的验证码
        stringRedisTemplate.delete(redisKey);

        // 2. 校验用户名和密码
        String username = userLoginRequest.getUserAccount();
        String password = userLoginRequest.getUserPassword();

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);

        try {
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (Objects.isNull(authenticate)) {
                return Result.error("用户名或者密码错误");
            }

            // 获取用户信息
            LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
            String token = UUID.randomUUID().toString();

            // 判断用户的状态
            if ("1".equals(loginUser.getStatus())) {
                return Result.error("账户已停用");
            }

            // 3. 生成 Token 并返回登录结果
            UserLoginVO userLoginVO = BeanUtil.copyProperties(loginUser.getUser(), UserLoginVO.class);
            Map<String, String> userMap = new HashMap<>();
            userMap.put("UserName", userLoginVO.getUserName());
            userMap.put("UserAvatar", userLoginVO.getAvatar());
            userMap.put("user_id", String.valueOf(userLoginVO.getUserId()));

            String tokenKey = LOGIN_USER_KEY + token;
            stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);
            stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);

            userLoginVO.setToken(token);
            request.getSession().setAttribute("user", userLoginVO);
            return Result.success(userLoginVO);
        } catch (AuthenticationException e) {
            return Result.error("用户名或者密码错误");
        }
    }

    @Override
    public Result<String> changePassword(Long userId, UpdatePasswordRequest request) {
        User user = userMapper.getUserById(userId);
        if (user == null) {
            return Result.error("用户不存在");
        }

        // 校验旧密码是否正确
        if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
            return Result.error("原密码错误");
        }

        // 更新为新密码，通过 Mapper SQL
        String encodedPassword = passwordEncoder.encode(request.getNewPassword());
        userMapper.updatePasswordByUserId(userId, encodedPassword);

        return Result.success("密码修改成功");
    }


    public User getLoginUser(String token) {
        if (token == null) {
            return null;
        }

        String tokenKey = LOGIN_USER_KEY + token;
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(tokenKey);
        if (userMap.isEmpty()) {
            return null;
        }

        User loginUser = new User();
        loginUser.setUserId(Long.parseLong((String) userMap.get("user_id")));
        loginUser.setUserName((String) userMap.get("UserName"));
        loginUser.setAvatar((String) userMap.get("UserAvatar"));
        return loginUser;
    }


    /**
     * 退出登录
     *
     * @return Result
     */
    @Override
    public Result logout(LogoutRequest logoutRequest) {
        String token = logoutRequest.getToken();
        // 确保token不为空
        if (token == null || token.isEmpty()) {
            return Result.error("Token不能为空");
        }
        // 生成token在Redis中的key
        String tokenKey = LOGIN_USER_KEY + token.trim();;
        System.out.println(tokenKey);
        // 检查该token是否存在于Redis中
        Boolean aBoolean = stringRedisTemplate.hasKey(tokenKey);
        if (aBoolean) {
            // 删除该token的用户数据
            stringRedisTemplate.delete(tokenKey);
            return Result.success("退出登录成功");
        } else {
            // 如果token不存在，返回失败信息
            return Result.error("无效的token或用户未登录");
        }
    }

    /**
     * 用户注册
     * @param userRegisterRequest
     * @return
     */
    @Override
    public Result<UserPersonalVO> userRegister(UserRegisterRequest userRegisterRequest) {
        String username = userRegisterRequest.getUserAccount();
        // 1. 获取密码
        String password = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();

        // 2. 校验密码是否一致
        if (!password.equals(checkPassword)) {
            return Result.error("两次输入的密码不一致");
        }

        // 3. 校验密码格式
        if (password.length() < 8) {
            return Result.error("用户密码过短，至少需要8个字符");
        }

        // 4. 校验用户名是否存在
        User existingUser = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUserName, username));
        if (existingUser != null) {
            return Result.error("用户名已存在");
        }

        // 5. 创建新用户对象
        User newUser = new User();
        newUser.setUserName(username);

        // 使用合法的强度值（例如10）
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(10);
        newUser.setPassword(passwordEncoder.encode(password)); // 正确加密密码

        // 6. 生成随机昵称
        String randomNickName = generateRandomNickName();
        newUser.setNickName(randomNickName);

        // 7. 保存用户到数据库
        int insertResult = userMapper.insert(newUser);
        if (insertResult <= 0) {
            return Result.error("注册失败，请重试");
        }

        // 8. 返回成功结果
        UserPersonalVO userPersonalVO = BeanUtil.copyProperties(newUser, UserPersonalVO.class);
        return Result.success(userPersonalVO);
    }

    /**
     * 生成随机昵称
     * @return 随机昵称
     */
    private String generateRandomNickName() {
        SecureRandom random = new SecureRandom();
        byte[] randomBytes = new byte[8];
        random.nextBytes(randomBytes);
        return Base64.getUrlEncoder().withoutPadding().encodeToString(randomBytes);
    }

    // 减少用户的论文总数
    public void decrementUserPaperCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("paper_count=paper_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的论文总数
    public void incrementUserPaperCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("paper_count=paper_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的专利总数
    public void decrementUserPatentCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("patent_count=patent_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的专利总数
    public void incrementUserPatentCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("patent_count=patent_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的软件著作数量
    public void decrementUserCopyrightCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("copyright_count=copyright_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的软件著作数量
    public void incrementUserCopyrightCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("copyright_count=copyright_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的个人获奖总数
    public void decrementUserAwardPersonalCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("awardPersonal_count=awardPersonal_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的个人获奖总数
    public void incrementUserAwardPersonalCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("awardPersonal_count=awardPersonal_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的学生获奖总数
    public void decrementUserAwardStudentCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("awardStudent_count=awardStudent_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的学生获奖总数
    public void incrementUserAwardStudentCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("awardStudent_count=awardStudent_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的继续教育材料总数
    public void decrementUserMaterialCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("material_count=material_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的继续教育材料总数
    public void incrementUserMaterialCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("material_count=material_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的著作信息总数
    public void decrementUserPublicationCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("publication_count=publication_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的著作信息总数
    public void incrementUserPublicationCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("publication_count=publication_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的新闻报道上传总数
    public void decrementUserReportCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("report_count=report_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的新闻报道上传总数
    public void incrementUserReportCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("report_count=report_count+1").eq(User::getUserId, userId).update();
    }

    // 减少用户的档案资料总数
    public void decrementUserCertificateinfoCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("certificateinfo_count=certificateinfo_count-1").eq(User::getUserId, userId).update();
    }

    // 增加用户的档案资料总数
    public void incrementUserCertificateinfoCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("certificateinfo_count=certificateinfo_count+1").eq(User::getUserId, userId).update();
    }

    //增加用户的纵向课题数量
    public void incrementUserLongitudinalCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("longitudinal_project_count=longitudinal_project_count+1").eq(User::getUserId, userId).update();
    }


    // 增加用户的其它资料总数
    public void incrementUserOtherCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("other_count=other_count+1").eq(User::getUserId, userId).update();
    }
    //减少用户的纵向课题数量
    public void decrementUserLongitudinalCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("longitudinal_project_count=longitudinal_project_count-1").eq(User::getUserId, userId).update();
    }

    // 减少用户的其它资料总数
    public void decrementUserOtherCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("other_count=other_count-1").eq(User::getUserId, userId).update();
    }

    //新增用户的横向课题数量
    public void incrementUserHorizontalCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("horizontal_project_count=horizontal_project_count+1").eq(User::getUserId, userId).update();
    }

    //减少用户的横向课题数量
    public void decrementUserHorizontalCount() {
        Long userId = UserHolder.getUser().getUserId();
        lambdaUpdate().setSql("horizontal_project_count=horizontal_project_count-1").eq(User::getUserId, userId).update();
    }


    @Override
    public Result<UserResultCountVO> getUserPersonalCount() {
        Long userId = UserHolder.getUser().getUserId();
        if (userId != null) {
            UserResultCountVO userResultCountVO = userMapper.getUserResultCountByUserId(userId);
            return Result.success(userResultCountVO);
        } else {
            return Result.error("用户未登录或用户ID为空");
        }
    }

    @Override
    public Result<UserPersonalVO> updateUserById(UserPersonalVO userPersonalVO) {
        // 将 UserPersonalVO 转换为 User 实体类
        User user = User.builder()
                .avatar(userPersonalVO.getAvatar())
                .nickName(userPersonalVO.getNickName())
                .phoneNumber(userPersonalVO.getPhoneNumber())
                .email(userPersonalVO.getEmail())
                .title(userPersonalVO.getTitle())
                .department(userPersonalVO.getDepartment())
                .userId(UserHolder.getUser().getUserId())
                .build();

        // 更新用户信息
        int updatedRows = userMapper.updateUserById(user);

        // 检查更新是否成功
        if (updatedRows > 0) {
            return Result.success(userPersonalVO);
        } else {
            return Result.error("更新用户信息失败");
        }
    }

    /**
     * 根据userId查询用户昵称
     */
    public String getUserNickNameByUserId() {
        Long userId = UserHolder.getUser().getUserId();
       return userMapper.getUserNickNameByUserId(userId);

    }

    @Override
    public String getUserNameByUserId(Long userId) {
        User user = lambdaQuery().select(User::getNickName).eq(User::getUserId, userId)
                .one();

        return user.getNickName();
    }

    @Override
    public String getUserAvatarByUserId(Long userId) {
        User user = lambdaQuery().select(User::getAvatar).eq(User::getUserId, userId)
                .one();
        return user.getAvatar();
    }



    /**
     * 获得脱敏后的用户信息
     *
     * @param user
     * @return
     */
    @Override
    public UserPersonalVO getUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserPersonalVO userVO = new UserPersonalVO();
        BeanUtil.copyProperties(user, userVO);
        return userVO;
    }


    /**
     * 根据用户的userId查询个人信息
     */
    public AddMemberVO getUserPersonalInfo(Long userId) {
        User user = lambdaQuery().eq(User::getUserId, userId).one();

        AddMemberVO addMemberVO = AddMemberVO.builder()
                .avatar(user.getAvatar())
                .nickName(user.getNickName())
                .userId(user.getUserId())
                .build();
        return addMemberVO;
    }

    /**
     * 根据userId查看用户是否存在
     * @param userId
     * @return
     */
    @Override
    public boolean isUserExist(Long userId) {
        if (userId == null || userMapper == null) {
            return false;
        }

        try {
            // 使用 lambdaQuery() 方法进行查询
            return lambdaQuery()
                    .eq(User::getUserId, userId)
                    .count() > 0;
        } catch (Exception e) {

            return false;
        }
    }



}
